package com.distributeredis.redis_springboot.forAndThreadAndCompleTableFuture.service.impl;

import com.distributeredis.redis_springboot.forAndThreadAndCompleTableFuture.entity.UserDTO;
import com.distributeredis.redis_springboot.forAndThreadAndCompleTableFuture.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.*;

@Service
@Slf4j
public class TestServiceImpl implements TestService {
    @Autowired
    @Qualifier("asyncTaskExecutor")
    private Executor asyncTaskExecutor;
    @Autowired
    private ExecutorService executorService;
    @Override
    public void test() throws ExecutionException, InterruptedException {
//        ExecutorService executorService = Executors.newFixedThreadPool(10);
//        list集合是不安全的
        List<CompletableFuture> futures = Collections.synchronizedList(new ArrayList<>());
        List<String> list = Collections.synchronizedList(new ArrayList<>());
        List<UserDTO> userDTOS = Collections.synchronizedList(new ArrayList<>());
        for (int i = 0; i < 1000; i++) {
            int index = i;
            CompletableFuture cf = CompletableFuture.supplyAsync(() -> {
                String uuid = null;
                try {
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                     uuid = UUID.randomUUID().toString();
                     UserDTO userDTO = new UserDTO().setUserId(uuid).setUserName("zs").setAge(1);
                     userDTOS.add(userDTO);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                return list.add(uuid);
            },asyncTaskExecutor);
            futures.add(cf);
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

        System.out.println("线程结束：：：：：：：：：：：：：");
        System.out.println(futures);
        for (CompletableFuture future : futures) {
            Object o = future.get();
            System.out.println(o);
        }
        System.out.println(list);
        System.out.println("运行的结果总数为：："+list.size());
        System.out.println(userDTOS);
        log.info(""+ list.size());
    }

    @Override
    public void test1() throws Exception {
        System.out.println("main start...");

        List<String> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
//        自定义两个线程 t1,t2
        Thread t1 = new Thread(()-> {
            try {
                Thread.sleep(1000);
                list1.add("1");
                System.out.println(Thread.currentThread().getName()+": t1线程");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        Thread t2 = new Thread(()-> {
            try {
                Thread.sleep(2000);
                list2.add("2");
                System.out.println(Thread.currentThread().getName()+": t2线程");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        // 开启两个线程
        t1.start();
        t2.start();
//        等待两个线程运行完毕，再往下运行逻辑
        t1.join();
        t2.join();

        System.out.println("main end...");
        System.out.println(list1+"\n"+list2);
    }

    @Override
    public void test2() throws InterruptedException, ExecutionException {
        List<Future> futures = Collections.synchronizedList(new ArrayList<>());
        List<UserDTO> userDTOS = Collections.synchronizedList(new ArrayList<>());
//        计数器
        CountDownLatch latch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            Future<UserDTO> future = executorService.submit(() -> {
                UserDTO userDTO = new UserDTO();
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName());
                    userDTO.setUserId(UUID.randomUUID().toString());
                    userDTO.setUserName("张三");
                    userDTO.setAge(22);
                    userDTOS.add(userDTO);
                } catch (Exception e) {
                    log.error("出现了异常："+e);
                }finally {
                    latch.countDown();
                }
                return userDTO;
            });
            futures.add(future);
        }
        // 等待所有线程执行完毕
        latch.await();
        System.out.println("所有线程均已执行完毕！！！！！！");
        for (Future future : futures) {
            System.out.println(future.get());
        }
    }

    @Override
    public void test3() {
//        也可以使用CountDownLatch来控制线程全部执行完毕
        UserDTO user = null;
        List<UserDTO> userDTOS = new ArrayList<>();
        List<UserDTO> userCopys = Collections.synchronizedList(new ArrayList<>());
        List<UserDTO> userCopys1 = Collections.synchronizedList(new ArrayList<>());
        for (int i = 0; i < 500000; i++) {
            user = new UserDTO(i+"","name"+i,18);
            userDTOS.add(user);
        }
        List<Future> futures = Collections.synchronizedList(new ArrayList<>());
        for (UserDTO userDTO : userDTOS) {
            Future future = executorService.submit(() -> {
                String userId = userDTO.getUserId();
                userCopys1.add(new UserDTO(userDTO.getUserId(),userDTO.getUserName(),userDTO.getAge()));
                if ("3".equals(userId)) {
                    try{
                        int i = 1/0;
                    }catch (Exception e) {
                        log.error(userId);
                        return;
                    }
                }
                System.out.println(userDTO.getUserId());
                userCopys.add(new UserDTO(userDTO.getUserId(),userDTO.getUserName(),userDTO.getAge()));
            });
            futures.add(future);
        }
        try {
            for (Future future : futures) {
                future.get();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("end");
        System.out.println(userCopys.size());
        System.out.println(userCopys1.size());
    }
}
